/*
 * 文件名： CiticCcHexDump.java
 * 
 * 工程名称: bis-bank-citic
 *
 * Gopay
 *
 * 创建日期： 2016年6月22日
 *
 * Copyright(C) 2016, by www.gopay.com.cn Inc.All rights reserved.
 *
 * 原始作者: 宣广海
 *
 */
package com.gopay.bis.citic.expay.operation;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

/**
 * 
 *
 * @author 宣广海
 *
 * @version 
 *
 * @since 2016年6月22日
 */
public class CiticCcHexDump {
	/** Stream that understands "printing" */
	protected PrintStream pStream;

	// 整个Buffer的前缀
	protected String sBufferPrefix = "";
	// 每行的前缀
	protected String sLinePrefix = "";
	// 每行的后缀
	protected String sLineSuffix = "";
	// 整个Buffer的后缀
	protected String sBufferSuffix = "";

	/**
	 * 
	 */
	public CiticCcHexDump()
	{
		super();
	}

	/**
	 * @param sBufferPrefix
	 * @param sLinePrefix
	 * @param sLineSuffix
	 * @param sBufferSuffix
	 */
	public CiticCcHexDump(String sBufferPrefix, String sLinePrefix, String sLineSuffix, String sBufferSuffix)
	{
		super();
		this.sBufferPrefix = sBufferPrefix;
		this.sLinePrefix = sLinePrefix;
		this.sLineSuffix = sLineSuffix;
		this.sBufferSuffix = sBufferSuffix;
	}

	static void hexDigit(PrintStream ps, byte x)
	{
		char c;

		c = (char) ((x >> 4) & 0x0F);
		if (c > 9)
			c = (char) ((c - 10) + 'A');
		else
			c = (char) (c + '0');
		ps.write(c);
		c = (char) (x & 0x0F);
		if (c > 9)
			c = (char) ((c - 10) + 'A');
		else
			c = (char) (c + '0');
		ps.write(c);
	}

	protected void hexDumpGBK(byte aBuffer[], int offset, int length, OutputStream aStream) throws IOException
	{
		int c1;
		int c2;
		int thisLineLength;
		int ccpair = 0;

		// 整个Buffer的前缀
		pStream = new PrintStream(aStream);
		pStream.print(sBufferPrefix);

		for (int ptr = 0; ptr < length;)
		{
			if (length - ptr >= 16)
				thisLineLength = 16;
			else
				thisLineLength = length - ptr;

			// 每行的前缀
			pStream.print(sLinePrefix);
			// >>> 右移，高位补零； >> 右移，高位补和原符号为相同的数。对于正数没差别
			hexDigit(pStream, (byte) ((ptr >>> 24) & 0xFF));
			hexDigit(pStream, (byte) ((ptr >>> 16) & 0xFF));
			hexDigit(pStream, (byte) ((ptr >>> 8) & 0xFF));
			hexDigit(pStream, (byte) (ptr & 0xff));
			pStream.print(":");

			for (int j = 0; j < 16; j++) /* byte order of this line */
			{
				if (j < thisLineLength)
				{
					if (j == 8)
						pStream.print("-");
					else
						pStream.print(" ");
					hexDigit(pStream, aBuffer[offset + ptr + j]);
				}
				else
					pStream.print("   ");
			}

			pStream.print(" | ");
			for (int i = 0; i < thisLineLength; i++)
			{
				if (i == 0 && ccpair > 0)
				{
					ccpair = 0;
					pStream.write('_');
				}
				else
				{
					if (ccpair == 0)
					{
						c1 = aBuffer[offset + ptr + i] & 0xFF;
						if (c1 >= 0x81 && c1 <= 0xFE)
						{
							c2 = aBuffer[offset + ptr + i + 1] & 0xFF;
							if (c2 != 0x7F && c2 >= 0x40 && c2 <= 0xFE)
							{
								ccpair = 1; /* DBCS left byte */
								pStream.write(aBuffer[offset + ptr + i]);
							}
							else
								pStream.print(".");
						}
						else if (aBuffer[offset + ptr + i] >= 0x20 && aBuffer[offset + ptr + i] < 0x80)
							pStream.write(aBuffer[offset + ptr + i]);
						else
							pStream.print(".");
					}
					else
					{
						ccpair = 0; /* DBCS right byte */
						pStream.write(aBuffer[offset + ptr + i]);
					}
				}
			}
			if (ccpair > 0 && thisLineLength == 16)
			{
				pStream.write(aBuffer[offset + ptr + 16]);
			}
			// 每行的后缀
			pStream.println(sLineSuffix);
			// offset += thisLineLength;
			ptr += thisLineLength;
		}
		// 整个Buffer的后缀
		if (sBufferSuffix != null && !sBufferSuffix.equals("")) pStream.println(sBufferSuffix);
	}

	public String hexDumpGBK(byte aBuffer[], int offset, int length)
	{
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		try
		{
			hexDumpGBK(aBuffer, offset, length, outStream);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		return (outStream.toString());
	}

	public String hexDumpGBK(byte aBuffer[])
	{
		return hexDumpGBK(aBuffer, 0, aBuffer.length);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		long beginTime = System.currentTimeMillis();
		String s1 = "My HexDump, 支持中文, M.L.Y 2013.12.啊镕ABCabc. " +
		"Java: >>> 右移，高位补零；>> 右移，高位补和原符号为相同的数。对于正数没差别.";
		//CiticCcHexDump hd = new CiticCcHexDump();
		CiticCcHexDump hd = new CiticCcHexDump("---Begin HexDump:\n", "[", "]", "---End HexDump.\n");
		System.out.print(hd.hexDumpGBK(s1.getBytes()));
		long endTime = System.currentTimeMillis();
		System.out.println("HexDump 耗时: " + (endTime - beginTime) + " ms.");
	}
}
